home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Dev / SmallTalk / CompiledMethod.st < prev    next >
Text File  |  1995-08-25  |  18KB  |  606 lines

  1. "======================================================================
  2. |
  3. |   CompiledMethod Method Definitions
  4. |
  5.  ======================================================================"
  6.  
  7.  
  8. "======================================================================
  9. |
  10. | Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  11. | Written by Steve Byrne.
  12. |
  13. | This file is part of GNU Smalltalk.
  14. |
  15. | GNU Smalltalk is free software; you can redistribute it and/or modify it
  16. | under the terms of the GNU General Public License as published by the Free
  17. | Software Foundation; either version 1, or (at your option) any later version.
  18. | GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
  19. | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  20. | FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  21. | details.
  22. | You should have received a copy of the GNU General Public License along with
  23. | GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
  24. | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
  25. |
  26.  ======================================================================"
  27.  
  28.  
  29. "
  30. |     Change Log
  31. | ============================================================================
  32. | Author       Date       Change 
  33. | sbb         15 Sep 91      Adjusted to account for larger numbers of primitives,
  34. |              literals, and temporaries.
  35. |
  36. | sbb         16 Mar 91      Class creation now separate statement.
  37. |
  38. | sbb         22 Sep 90      Fixed printOn method to account for change to String
  39. |              printOn:.
  40. |
  41. | sbyrne     27 Dec 89      Added real print method for compiled methods.
  42. |
  43. | sbyrne      6 Sep 89      Added lots of methods: inspect, =, hash, method
  44. |              cateogry, methodSourceCode, methodSourceString, and
  45. |              some private accessors such as bytecodeAt:.
  46. |
  47. | sbyrne     25 Apr 89      created.
  48. |
  49. "
  50.  
  51. ArrayedCollection variableByteSubclass: #CompiledMethod
  52.           instanceVariableNames: 'descriptor methodHeader'
  53.           classVariableNames: ''
  54.           poolDictionaries: ''
  55.           category: nil
  56. !
  57.  
  58. CompiledMethod comment:
  59. 'I represent methods that have been compiled.  I can recompile
  60. methods from their source code, I can invoke Emacs to edit the source code
  61. for one of my instances, and I know how to access components of my
  62. instances.' !
  63.  
  64.  
  65. "Make sure that this symbol is defined, even if it doesn't work just
  66. yet."
  67. Smalltalk at: #Debugger put: nil!
  68.  
  69. !CompiledMethod methodsFor: 'basic'!
  70.  
  71. methodCategory
  72.     ^descriptor category
  73. !
  74.  
  75. methodCategory: aCategory
  76.     ^descriptor category: aCategory
  77. !
  78.  
  79. methodSourceCode
  80.     ^descriptor sourceCode
  81. !
  82.  
  83. methodSourceString
  84.     ^descriptor sourceString
  85. !
  86.  
  87. methodSourceFile
  88.     ^descriptor sourceFile
  89. !
  90.  
  91. methodSourcePos
  92.     ^descriptor sourcePos
  93. !
  94.  
  95. = aMethod
  96.     descriptor = aMethod getDescriptor ifFalse: [ ^false ].
  97.     methodHeader = aMethod getHeader ifFalse: [ ^false ].
  98.     1 to: self numLiterals do:
  99.         [ :i |  (self literalAt: i) = (aMethod literalAt: i)
  100.                 ifFalse: [ ^false ] ].
  101.     1 to: self numBytecodes do:
  102.         [ :i | (self bytecodeAt: i) = (aMethod bytecodeAt: i)
  103.                 ifFalse: [ ^false ] ].
  104.     ^true
  105. !
  106.  
  107. hash
  108.     | hashValue |
  109.     hashValue _ descriptor hash.
  110.     hashValue _ ((hashValue bitShift: 1)
  111.                   bitXor: methodHeader hash)
  112.           bitAnd: 16r1FFFFFFF.
  113.     1 to: self numLiterals do:
  114.         [ :i | hashValue _ ((hashValue bitShift: 1)
  115.                             bitXor: (self literalAt: i) hash)
  116.                      bitAnd: 16r1FFFFFFF ].
  117.     1 to: self numBytecodes do:
  118.         [ :i | hashValue _ ((hashValue bitShift: 1)
  119.                              bitXor: (self bytecodeAt: i) hash)
  120.                      bitAnd: 16r1FFFFFFF ].
  121.     ^hashValue
  122. !!
  123.  
  124.  
  125.  
  126. !CompiledMethod methodsFor: 'method header accessors'!
  127.  
  128. "The structure of a method header is as follows (from mstinterp.h)
  129.  
  130. ### fix this up 
  131.    3                   2                   1 
  132.  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  133. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  134. |1|.|.|.|.|.|flg| prim index    | #args   | #temps  | #literals |
  135. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  136.  
  137. literals 6 0..5
  138. temporarycount 5 6..10
  139. args 5 11..15
  140. primitiveIndex 8 16..23
  141. flags 2 24-25
  142. flags 0 -- use arguments as they are, ignore prim index
  143. flags 1 -- return self
  144. flags 2 -- return instance variable
  145. flags 3 -- call the primitive indexed by primIndex
  146. "
  147.  
  148. flags
  149.     "The xor here is related to 1) the fact that the the flags field overlaps 
  150.      with the penultimate msb, and 2) the way that integers are encoded."
  151.     ^((methodHeader bitShift: -29) bitAnd: 16r3) bitXor: 2
  152. !
  153.  
  154. primitive
  155.     ^(methodHeader bitShift: -19) bitAnd: 16r3FF
  156. !
  157.  
  158. numArgs
  159.     | flags |
  160.     flags _ self flags.
  161.     (flags = 2) | (flags = 3)
  162.         ifTrue: [ ^0 ].
  163.     ^(methodHeader bitShift: -14) bitAnd: 16r1F
  164. !
  165.  
  166. numTemps
  167.     self flags = 0
  168.         ifFalse: [ ^0 ].
  169.     ^(methodHeader bitShift: -8) bitAnd: 16r3F
  170. !
  171.  
  172. numLiterals
  173.     self flags = 0
  174.         ifFalse: [ ^0 ].
  175.     ^methodHeader bitAnd: 16rFF
  176. !!
  177.  
  178.  
  179.  
  180. !CompiledMethod methodsFor: 'copying'!
  181.  
  182. shallowCopy
  183.     ^(CompiledMethod newMethod: self basicSize
  184.              header: methodHeader) shallowCopyMethodContents: self
  185. !
  186.  
  187. deepCopy
  188.     ^(CompiledMethod newMethod: self basicSize
  189.              header: methodHeader) deepCopyMethodContents: self
  190. !!
  191.  
  192.  
  193.  
  194. !CompiledMethod methodsFor: 'debugging'!
  195.  
  196. inspect
  197.     | class instVars |
  198.     class _ self class.
  199.     instVars _ class instVarNames.
  200.     stdout nextPutAll: 'An instance of '.
  201.     class printNl.
  202.     1 to: (instVars size - 1) do: "assumes methodHeader is last inst var"
  203.         [ :i | stdout nextPutAll: '  ';
  204.            nextPutAll: (instVars at: i);
  205.            nextPutAll: ': '.
  206.            (self objectAt: i)  printNl ].
  207.     stdout nextPutAll: '  Header Flags: '; nl;
  208.         nextPutAll: '    flags: '.
  209.     self flags printNl.
  210.     stdout nextPutAll: '    primitive index: '.
  211.     self primitive printNl.
  212.     stdout nextPutAll: '    number of arguments: '.
  213.     self numArgs printNl.
  214.     stdout nextPutAll: '    number of temporaries: '.
  215.     self numTemps printNl.
  216.     stdout nextPutAll: '    number of literals: '.
  217.     self numLiterals printNl.
  218.     self numLiterals > 0
  219.         ifTrue: [ stdout nextPutAll: '  literals: ['; nl.
  220.           1 to: self numLiterals do:
  221.               [ :i | stdout nextPutAll: '    '.
  222.                  i print.
  223.                  stdout nextPutAll: ': '.
  224.                  (self literalAt: i) storeNl ].
  225.           stdout nextPutAll: '  ]'; nl ]
  226. !!
  227.  
  228.  
  229.  
  230. !CompiledMethod methodsFor: 'debugging'!
  231. breakpointAt: byteIndex
  232.     "self notYetImplemented"
  233.     Debugger recordOldByte: (self bytecodeAt: byteIndex)
  234.          atIndex: byteIndex
  235.          forMethod: self.
  236.     self bytecodeAt: byteIndex put: Debugger debugByte
  237. !
  238.  
  239. breakAtLine: lineNumber
  240.     self notYetImplemented
  241. !
  242.  
  243. removeBreakpointAt: byteIndex
  244.     | oldByte |
  245.     oldByte _ Debugger origByteAt: byteIndex forMethod: self.
  246.     oldByte notNil 
  247.     ifTrue: [ self bytecodeAt: byteIndex put: oldByte ]
  248. !!
  249.  
  250.  
  251.  
  252. !CompiledMethod methodsFor: 'printing'!
  253.  
  254. printOn: aStream
  255.     "### This could be more interesting, such as calling the decompiler, or
  256.      printing out the byte codes, or ... yeah, yeah, that's it, the byte
  257.      codes...also need to decode the header information to display that
  258.      interesting information"
  259.     | primIndex numLits |
  260.     true 
  261.     ifTrue: [ aStream nextPutAll: 'a CompiledMethod' ]
  262.     ifFalse: 
  263.         [ aStream nextPutAll: 'Header Info: '.
  264.           (primIndex _ self primitive) > 0 
  265.           ifTrue: [ aStream nextPutAll: 'Primitive: ' ].
  266.           numLits _ self numLiterals.
  267.           aStream nextPutAll: ' # Args: '.
  268.           (self numArgs) printOn: aStream.
  269.           aStream nextPutAll: ' # Temps: '.
  270.           (self numTemps) printOn: aStream.
  271.           aStream nextPutAll: ' # Literals: '.
  272.           numLits printOn: aStream. aStream nl.
  273.           numLits > 0 
  274.           ifTrue: [ aStream nextPutAll: 'Literals'; nl;
  275.                 nextPutAll: '--------'; nl.
  276.                 1 to: numLits do:
  277.                 [ :i | aStream nextPutAll: '    ['.
  278.                        i printOn: aStream.
  279.                        aStream nextPutAll: ']: '.
  280.                        (self literalAt: i) printOn: aStream.
  281.                        aStream nl ] ].
  282.           " Emit header info here too "
  283.              aStream nextPutAll: 'Byte codes'; nl;
  284.               nextPutAll: '----------'; nl.
  285.           self printByteCodesOn: aStream ]
  286.                          
  287. !
  288.  
  289. storeOn: aStream
  290.     self printOn: aStream
  291. !!
  292.  
  293.  
  294.  
  295. !CompiledMethod methodsFor: 'private'!
  296.  
  297. shallowCopyMethodContents: aMethod 
  298.     "Don't need to copy the method header; it's already done"
  299.     descriptor _ aMethod getDescriptor.
  300.     1 to: aMethod numLiterals do:
  301.         [ :i | self literalAt: i put: (aMethod literalAt: i) ].
  302.     1 to: aMethod numBytecodes do:
  303.         [ :i | self bytecodeAt: i put: (aMethod bytecodeAt: i) ]
  304. !
  305.  
  306. deepCopyMethodContents: aMethod
  307.     "Don't need to copy the method header; it's already done"
  308.     descriptor _ aMethod getDescriptor deepCopy.
  309.     1 to: aMethod numLiterals do:
  310.         [ :i | self literalAt: i put: (aMethod literalAt: i) deepCopy ].
  311.     1 to: aMethod numBytecodes do:
  312.         [ :i | self bytecodeAt: i put: (aMethod bytecodeAt: i) ]
  313. !
  314.  
  315. printByteCodesOn: aStream
  316.     | numBytes i |
  317.     i _ 1.
  318.     numBytes _ self numBytecodes.
  319.     [ i <= numBytes ] whileTrue:
  320.     [ i _ i + (self printByteAt: i on: aStream) ]
  321. !
  322.  
  323.  
  324. printByteAt: anIndex on: aStream
  325.     | byte nextByte skip |
  326.     byte _ self bytecodeAt: anIndex.
  327.     byte == 127 "Debugger debugByte"
  328.     ifTrue: [ byte _ Debugger origByteAt: anIndex forMethod: self ].
  329.     skip _ 1.
  330.     aStream nextPutAll: '    ['.
  331.     anIndex printOn: aStream.
  332.     aStream nextPutAll: ']: '.
  333.     byte < 95 ifTrue:
  334.     [ self printIndexedAt: anIndex on: aStream ].
  335.     (byte between: 96 and: 111) ifTrue:
  336.     [ self emitSimplePop: byte on: aStream ].
  337.     (byte between: 112 and: 125) ifTrue: 
  338.     [ self emitBuiltin: byte on: aStream ].
  339.     "127 is the debugger breakpoint and we don't get it here"
  340.     byte == 128 ifTrue: 
  341.     [ skip _ 2.
  342.       self print2BytePush: (self bytecodeAt: anIndex + 1) on: aStream ].
  343.     byte == 129 ifTrue: 
  344.     [ skip _ 2.
  345.       self print2ByteStackOp: 'store' at: anIndex on: aStream ].
  346.     byte == 130 ifTrue: 
  347.     [ skip _ 2.
  348.       self print2ByteStackOp: 'pop and store' at: anIndex on: aStream ].
  349.     (byte between: 131 and: 134) ifTrue: 
  350.     [ skip _ self emitIndexedSend: anIndex on: aStream ].
  351.     byte == 135 ifTrue:
  352.     [ aStream nextPutAll: 'pop stack top ' ].
  353.     byte == 136 ifTrue:
  354.     [ aStream nextPutAll: 'duplicate stack top' ].
  355.     byte == 137 ifTrue: 
  356.     [ aStream nextPutAll: 'push current context' ].
  357.     (byte between: 138 and: 143) ifTrue:
  358.     [ aStream nextPutAll: 'ILLEGAL bytecode '.
  359.       byte printOn: aStream ].
  360.     (byte between: 144 and: 175) ifTrue:
  361.     [ skip _ self printJump: anIndex on: aStream ].
  362.     (byte between: 176 and: 191) ifTrue:
  363.     [ aStream nextPutAll: 'send arithmetic message "'.
  364.       (#(+            -           <            >
  365.          <=         >=          =            ~=
  366.          *            /           \\            @
  367.          bitShift:    //          bitAnd:     bitOr:)
  368.            at: (byte bitAnd: 15) + 1) printOn: aStream.
  369.       aStream nextPut: $" ].
  370.     (byte between: 192 and: 207) ifTrue:
  371.     [ aStream nextPutAll: 'send special message "'.
  372.       (#(at:        at:put:        size        next
  373.             nextPut:    atEnd        ==            class
  374.             blockCopy:    value        value:      do:
  375.         new            new:        x            y)
  376.            at: (byte bitAnd: 15) + 1) printOn: aStream.
  377.       aStream nextPut: $" ].
  378.     (byte between: 208 and: 255) ifTrue:
  379.     [ self printSmallArgSend: byte on: aStream ].
  380.     aStream nl.
  381.     ^skip
  382. !    
  383.  
  384. printIndexedAt: anIndex on: aStream
  385.     | byte index |
  386.     byte _ self bytecodeAt: anIndex.
  387.     byte <= 15 ifTrue:
  388.         [ ^self pushIndexed: 'Instance Variable' 
  389.         withIndex: (byte bitAnd: 15)
  390.         on: aStream ].
  391.     byte <= 31 ifTrue:
  392.     [ ^self pushIndexed: 'Temporary'
  393.         withIndex: (byte bitAnd: 15)
  394.         on: aStream ].
  395.     byte <= 63 ifTrue:
  396.     [ ^self pushIndexed: 'Literal'
  397.         withIndex: (byte bitAnd: 31)
  398.         on: aStream ].
  399.  
  400.     " >= 64 case here "
  401.     aStream nextPutAll: 'push Global Variable['.
  402.     (byte bitAnd: 31) printOn: aStream.
  403.     aStream nextPutAll: '] = '.
  404.     self printAssociationKeyFor: (byte bitAnd: 31) on: aStream
  405. !
  406.  
  407. pushIndexed: indexLabel withIndex: anIndex on: aStream
  408.     aStream nextPutAll: 'push '.
  409.     indexLabel printOn: aStream.
  410.     aStream nextPut: $[.
  411.     anIndex printOn: aStream.
  412.     aStream nextPut: $]
  413. !
  414.  
  415. emitSimplePop: byte on: aStream
  416.     (byte between: 96 and: 103) ifTrue:
  417.     [ aStream nextPutAll: 'pop and store instance variable['.
  418.       (byte bitAnd: 7) printOn: aStream.
  419.       aStream nextPut: $] ].
  420.     (byte between: 104 and: 111) ifTrue:
  421.     [ aStream nextPutAll: 'pop and store Temporary['.
  422.       (byte bitAnd: 7) printOn: aStream.
  423.       aStream nextPut: $] ].
  424. !
  425.  
  426. emitBuiltin: byte on: aStream
  427.     byte == 112 ifTrue: [ aStream nextPutAll: 'push self' ].
  428.     byte == 113 ifTrue: [ aStream nextPutAll: 'push true' ].
  429.     byte == 114 ifTrue: [ aStream nextPutAll: 'push false' ].
  430.     byte == 115 ifTrue: [ aStream nextPutAll: 'push nil' ].
  431.     byte == 116 ifTrue: [ aStream nextPutAll: 'push -1' ].
  432.     byte == 117 ifTrue: [ aStream nextPutAll: 'push 0' ].
  433.     byte == 118 ifTrue: [ aStream nextPutAll: 'push 1' ].
  434.     byte == 119 ifTrue: [ aStream nextPutAll: 'push 2' ].
  435.     byte == 120 ifTrue: [ aStream nextPutAll: 'return self' ].
  436.     byte == 121 ifTrue: [ aStream nextPutAll: 'return true' ].
  437.     byte == 122 ifTrue: [ aStream nextPutAll: 'return false' ].
  438.     byte == 123 ifTrue: [ aStream nextPutAll: 'return nil' ].
  439.     byte == 124 ifTrue: [ aStream nextPutAll: 'return Message stack top' ].
  440.     byte == 125 ifTrue: [ aStream nextPutAll: 'return Block stack top' ].
  441.     byte == 126 ifTrue: [ aStream nextPutAll: '### ILLEGAL BYTE CODE 126 ###' ]
  442. !
  443.  
  444. print2BytePush: byte on: aStream
  445.     self printIndexedPush: (byte bitAnd: 63)
  446.      type: (byte bitShift: -6)
  447.      on: aStream
  448. !
  449.  
  450. printIndexedPush: index type: typeIndex on: aStream
  451.     | typeName |
  452.     typeName _ self indexedLocationName: typeIndex.
  453.     aStream nextPutAll: 'push ';
  454.         nextPutAll: typeName;
  455.         nextPutAll: '['.
  456.     index printOn: aStream.
  457.     aStream nextPut: $].
  458.     typeIndex = 3 ifTrue:
  459.     [ aStream nextPutAll: ' = '.
  460.       self printAssociationKeyFor: index
  461.            on: aStream ]
  462. !
  463.  
  464. indexedLocationName: locIndex
  465.     ^#('Instance Variable' 'Temporary' 'Literal' 'Global Variable')
  466.     at: locIndex + 1
  467. !
  468.  
  469. print2ByteStackOp: opName at: anIndex on: aStream
  470.     | nextByte locationName locIndex |
  471.     nextByte _ self bytecodeAt: anIndex + 1.
  472.     locIndex _ nextByte bitShift: -6.
  473.     locationName _ self indexedLocationName: locIndex.
  474.     locIndex == 2 ifTrue: [ aStream nextPutAll: 'ILLEGAL ' ].
  475.     aStream nextPutAll: opName;
  476.         nextPutAll: locationName;
  477.         nextPutAll:'['.
  478.     (nextByte bitAnd: 63) printOn: aStream.
  479.     aStream nextPut: $].
  480.     locIndex == 3 ifTrue:
  481.     [ aStream nextPutAll: ' = '.
  482.       self printAssociationKeyFor: (nextByte bitAnd: 63) on: aStream ]
  483. !
  484.  
  485. emitIndexedSend: anIndex on: aStream
  486.     | byte byte1 byte2 toSuper |
  487.     byte _ self bytecodeAt: anIndex.
  488.     byte _ byte - 131.        "transform to 0..3"
  489.     byte <= 1 ifTrue: [ toSuper _ '' ]
  490.           ifFalse: [ toSuper _ 'to Super ' ].
  491.     (byte == 0) | (byte == 2)
  492.     ifTrue:
  493.         [ byte1 _ self bytecodeAt: anIndex + 1.
  494.           self emitGenericSend: toSuper index: (byte1 bitAnd: 31)
  495.            args: (byte1 bitShift: -5) on: aStream.
  496.           ^2 ]
  497.     ifFalse:
  498.         [ byte1 _ self bytecodeAt: anIndex + 1.
  499.           byte2 _ self bytecodeAt: anIndex + 2.
  500.           self emitGenericSend: toSuper index: byte2
  501.            args: byte1 on: aStream.
  502.           ^3]
  503. !
  504.  
  505.  
  506. emitGenericSend: toSuper index: anIndex args: numArgs on: aStream
  507.     aStream nextPutAll: 'send ';
  508.     nextPutAll: toSuper;
  509.     nextPutAll: 'selector '.
  510.     anIndex printOn: aStream.
  511.     aStream nextPutAll: ', '.
  512.     numArgs printOn: aStream.
  513.     aStream nextPutAll: ' args = '.
  514.     self printLiteralSymbolAt: anIndex on: aStream
  515. !
  516.  
  517. printJump: anIndex on: aStream
  518.     | byte |
  519.     byte _ self bytecodeAt: anIndex.
  520.     byte <= 151 ifTrue:
  521.     [ aStream nextPutAll: 'jump to '.
  522.       ((byte bitAnd: 7) + anIndex + 1 + 1 ) printOn: aStream.
  523.       ^1 ].
  524.     byte <= 159 ifTrue:
  525.     [ aStream nextPutAll: 'jump to '.
  526.       ((byte bitAnd: 7) + anIndex + 1 + 1 ) printOn: aStream.
  527.       aStream nextPutAll: ' if false'.
  528.       ^1 ].
  529.     byte <= 167 ifTrue:
  530.     [ aStream nextPutAll: 'jump to '.
  531.       (((byte bitAnd: 7) - 4) * 256 + (self bytecodeAt: anIndex + 1)
  532.           + anIndex + 2) printOn: aStream.
  533.       ^2 ].
  534.     byte <= 171 ifTrue:
  535.     [ aStream nextPutAll: 'pop and jump to '.
  536.       ((byte bitAnd: 3) * 256 + (self bytecodeAt: anIndex + 1)
  537.           + anIndex + 2) printOn: aStream.
  538.       aStream nextPutAll: ' if true'.
  539.       ^2 ].
  540.     byte <= 175 ifTrue:
  541.     [ aStream nextPutAll: 'pop and jump to '.
  542.       ((byte bitAnd: 3) * 256 + (self bytecodeAt: anIndex + 1)
  543.           + anIndex + 2) printOn: aStream.
  544.       aStream nextPutAll: ' if false'.
  545.       ^2 ]
  546. !
  547.  
  548. printSmallArgSend: byte on: aStream
  549.     | numArgs |
  550.     byte _ byte - 208.
  551.     numArgs _ byte // 16.
  552.     aStream nextPutAll: 'send selector '.
  553.     (byte bitAnd: 15) printOn: aStream.
  554.     aStream nextPutAll: ', '.
  555.     numArgs printOn: aStream.
  556.     numArgs == 1 
  557.     ifTrue: [ aStream nextPutAll: ' arg' ]
  558.     ifFalse: [ aStream nextPutAll: ' args' ].
  559.     aStream nextPutAll: ' = '.
  560.     self printLiteralSymbolAt: (byte bitAnd: 15) on: aStream
  561. !
  562.  
  563. printAssociationKeyFor: anIndex on: aStream
  564.     | assoc |
  565.     assoc _ self literalAt: anIndex + 1.
  566.     assoc key printOn: aStream
  567. !
  568.  
  569. printLiteralSymbolAt: anIndex on: aStream
  570.     (self literalAt: anIndex + 1) printOn: aStream
  571. !
  572.  
  573. getDescriptor
  574.     ^descriptor
  575. !
  576.  
  577. getHeader
  578.     ^methodHeader
  579. !
  580.  
  581. literalAt: anIndex
  582.     ^self objectAt: (anIndex + 2)
  583. !
  584.  
  585. literalAt: anInteger put: aValue
  586.     self objectAt: anInteger + 2 put: aValue
  587. !
  588.  
  589. numBytecodes
  590.     ^(self basicSize) - (self bytecodeStart)
  591. !
  592.  
  593. bytecodeAt: anIndex
  594.     ^self basicAt: (anIndex + self bytecodeStart)
  595. !
  596.  
  597. bytecodeAt: anIndex put: aValue
  598.     ^self basicAt: (anIndex + self bytecodeStart) put: aValue
  599. !
  600.  
  601. bytecodeStart
  602.     ^4 * self numLiterals
  603. !!
  604.